package com.gyx.lottery.service.mq;

import cn.hutool.core.date.DateUtil;
import com.gyx.lottery.common.exception.ServiceException;
import com.gyx.lottery.common.utils.JacksonUtil;
import com.gyx.lottery.common.utils.MailUtil;
import com.gyx.lottery.common.utils.SMSUtil;
import com.gyx.lottery.controller.param.DrawPrizeParam;
import com.gyx.lottery.dao.dataobject.ActivityPrizeDO;
import com.gyx.lottery.dao.dataobject.WinningRecordDO;
import com.gyx.lottery.dao.mapper.ActivityPrizeMapper;
import com.gyx.lottery.dao.mapper.WinningRecordMapper;
import com.gyx.lottery.service.DrawPrizeService;
import com.gyx.lottery.service.activitystatus.ActivityStatusManager;
import com.gyx.lottery.service.dto.ConvertActivityStatusDTO;
import com.gyx.lottery.service.enums.ActicityPrizeTiersEnum;
import com.gyx.lottery.service.enums.ActivityPrizeStatuseEnum;
import com.gyx.lottery.service.enums.ActivityStatusEnum;
import com.gyx.lottery.service.enums.ActivityUserStatusEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.gyx.lottery.common.config.DirectRabbitConfig.QUEUE_NAME;

@Component
@RabbitListener(queues  = QUEUE_NAME)
public class MqReceiver {
    private static final Logger logger= LoggerFactory.getLogger(MqReceiver.class);
    @Autowired
    DrawPrizeService drawPrizeService;
    @Autowired
    ActivityPrizeMapper activityPrizeMapper;
    @Autowired
    ActivityStatusManager activityStatusManager;
    @Autowired
    WinningRecordMapper winningRecordMapper;
    @Autowired
    ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    MailUtil mailUtil;
    @Autowired
    SMSUtil smsUtil;
@RabbitHandler
public void process(Map<String,String> message){
    logger.info("MqReceiver成功接收到消息:{}",
            JacksonUtil.writeVauleAsString(message));
    DrawPrizeParam param = JacksonUtil.readVaule
            (message.get("messageData"), DrawPrizeParam.class);
    //开始进行参数校验

    try {
        if(!drawPrizeService.checkDrawPrizeParam(param))
        {
            return ;
        }
        //开始进行状态扭转
        statusConvert(param);
        //进行中奖者记录的保存
        List<WinningRecordDO> winningRecordDOList =
                drawPrizeService.saveWinnnerRecords(param);
        //向中奖者发送通知
        sysnSendWinner(winningRecordDOList);
    }
    catch (ServiceException e){
        logger.error("mq处理消息异常 {},{}",e.getCode(),e.getMessage(),e);
        rollback(param);
        throw e;
    }
    catch (Exception e){
        logger.error("mq处理消息异常 {}",e.getMessage(),e);
        rollback(param);
        throw e;
    }
}

    private void sysnSendWinner(List<WinningRecordDO> winningRecordDOList) {
        threadPoolTaskExecutor.execute(()->sendMessage(winningRecordDOList));
        threadPoolTaskExecutor.execute(()->sendMail(winningRecordDOList));
}

    private void sendMail(List<WinningRecordDO> winningRecordDOList) {
    if(CollectionUtils.isEmpty(winningRecordDOList)){
        logger.info("中奖者信息为空");
        return ; }
    for(WinningRecordDO winningRecordDO:winningRecordDOList){
        logger.warn("ss:::::::::::{}",JacksonUtil.writeVauleAsString(winningRecordDO));
        String context = "Hi，" + winningRecordDO.getWinnerName() + "。恭喜你在"
                + winningRecordDO.getActivityName() + "活动中获得"
                + (ActicityPrizeTiersEnum.forName(winningRecordDO.getPrizeTier())).getMessage()
                + "：" + winningRecordDO.getPrizeName() + "。获奖时间为"
                + DateUtil.formatTime(winningRecordDO.getWinningTime()) + "，请尽快领 取您的奖励！";
        mailUtil.sendSampleMail(winningRecordDO.getWinnerEmail(),
                "中奖通知", context);
        }

    }

    private void sendMessage(List<WinningRecordDO> winningRecordDOList) {
        if(CollectionUtils.isEmpty(winningRecordDOList)){
            logger.info("中奖者信息为空");
            return ; }
        for(WinningRecordDO winningRecordDO:winningRecordDOList) {


            Map<String,Object>map=new HashMap<>();
            map.put("name",winningRecordDO.getWinnerName());
            map.put("activityName",winningRecordDO.getActivityName());
            map.put("prizeTiers",ActicityPrizeTiersEnum.forName(
                    winningRecordDO.getPrizeTier()).getMessage());
            map.put("prizeName",winningRecordDO.getPrizeName());
            map.put("winningTime",winningRecordDO.getWinningTime());
            smsUtil.sendMessage("SMS_474105234",
                    winningRecordDO.getWinnerPhoneNumber().getValue(),
                    JacksonUtil.writeVauleAsString(map));
        }


    }

    private void rollback(DrawPrizeParam param) {

        //判断活动状态是否需要进行回滚
        if(!statusNeedBack(param)){
            return ;
        }
        //活动状态进行回滚
        statusRollBack(param);
        //判断中奖者记录是否需要回滚
        if(!winnerNeedRollBack(param))
        {
            return ;
        }
        //中奖者记录进行回滚
        winnerRollBack(param);

    }

    private void winnerRollBack(DrawPrizeParam param) {
        drawPrizeService.deleteRecords(param.getActivityId(),param.getPrizeId());
    }

    private boolean winnerNeedRollBack(DrawPrizeParam param) {
       return winningRecordMapper.countByActivityIdAndPrizeId(param.getActivityId(),param.getPrizeId())>0;
    }

    private void statusRollBack(DrawPrizeParam param) {
        ConvertActivityStatusDTO convertActivityStatusDTO =new ConvertActivityStatusDTO();
        convertActivityStatusDTO.setActivityId(param.getActivityId());
        convertActivityStatusDTO.setPrizeId(param.getPrizeId());
        convertActivityStatusDTO.setTargetActivityStatus(ActivityStatusEnum.RUNNING);
        convertActivityStatusDTO.setTargetPrizeStatus(ActivityPrizeStatuseEnum.INIT);
        convertActivityStatusDTO.setUserIds(
                param.getWinnerList().stream()
                        .map(DrawPrizeParam.User::getUserId)
                        .collect(Collectors.toList())
        );
        convertActivityStatusDTO.setTargetUserStatus(ActivityUserStatusEnum.INIT);
        activityStatusManager.rollbackHandlerevent(convertActivityStatusDTO);

    }

    private boolean statusNeedBack(DrawPrizeParam param) {
        ActivityPrizeDO activityPrizeDO = activityPrizeMapper.selectByIdAndPrizeId(param.getActivityId(), param.getPrizeId());
        return activityPrizeDO.getStatus().
                equalsIgnoreCase(ActivityPrizeStatuseEnum.COMPLETED.name());
    }

    private void statusConvert(DrawPrizeParam param) {
        ConvertActivityStatusDTO convertActivityStatusDTO =new ConvertActivityStatusDTO();
        convertActivityStatusDTO.setActivityId(param.getActivityId());
        convertActivityStatusDTO.setPrizeId(param.getPrizeId());
        convertActivityStatusDTO.setTargetActivityStatus(ActivityStatusEnum.COMPLETED);
        convertActivityStatusDTO.setTargetPrizeStatus(ActivityPrizeStatuseEnum.COMPLETED);
        convertActivityStatusDTO.setUserIds(
                param.getWinnerList().stream()
                .map(DrawPrizeParam.User::getUserId)
                .collect(Collectors.toList())
        );
        convertActivityStatusDTO.setTargetUserStatus(ActivityUserStatusEnum.COMPLETED);
        activityStatusManager.handlerEvent(convertActivityStatusDTO);
    }

}
